// 本文件中包含了2个模块，AD按键和AD滑动变阻器(0-9.5K)
// 用于调节刹车增益

#include "app_key.h"

uint8_t r_ad_pwm_duty = 0;

//增益与(AB区间)最大占空比对应关系表：20200701 重新逐一采集.
const uint8_t Gain_tab[21][2] = 
{
	{0x00,0}, /*低频区*/
	{0x02,0}, /*低频区*/
	{0x04,10},
	{0x06,15},
	{0x08,20}, /*22%*/
	{0x0a,25}, 
	{0x0c,30}, 
	{0x0e,35},
	{0x10,40},
	{0x12,45},
	{0x14,50},
	{0x16,55},
	{0x18,60},
	{0x1a,68},
	{0x1c,73},
	{0x1e,77},
	{0x20,82}, /* Gain8 占空比3.6ms */
	{0x22,87},
	{0x24,92},
	{0x26,97},
	{0x28,97},
};


const uint8_t Gain_Res_Margin[21][3] = 
{
	{0x00,0x00,0x00}, /*低频区*/
	{0x02,0x00,0x00}, /*低频区*/
	{0x04,0xe7,0x66},
	{0x06,0xe4,0x64},
	{0x08,0xe3,0x63}, 
	{0x0a,0xe2,0x62}, 
	{0x0c,0xe2,0x62}, 
	{0x0e,0xe2,0x61},
	{0x10,0xe1,0x61},
	{0x12,0xe1,0x61},
	{0x14,0xe1,0x61},
	{0x16,0xe1,0x61},
	{0x18,0xe1,0x61},
	{0x1a,0xe1,0x61},
	{0x1c,0xe1,0x60},
	{0x1e,0xe1,0x60},
	{0x20,0xe0,0x60}, 
	{0x22,0xe0,0x60},
	{0x24,0xe0,0x60},
	{0x26,0xe0,0x60},
	{0x28,0xe0,0x60},
};

e_pwm_mod PWM_Mode = PULSE;

stc_slide_res_t slide_res;

Power_t Pwr;

//uint8_t brake_pwm_flag = 0;  //刹车输出标志

/*
原PWM引脚重初始化普通IO
*/
void PWMPin_reinit_NormalPin(void)
{
	stc_gpio_cfg_t stcGpioCfg;
    
    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); 
    
    ///< 端口方向配置->输出 
    stcGpioCfg.enDir = GpioDirOut;
    ///< 端口上下拉配置-> none
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdEnable;
	stcGpioCfg.enDrv = GpioDrvH;
	stcGpioCfg.enCtrlMode = GpioAHB;
	
    Gpio_Init(GpioPortA, GpioPin0, &stcGpioCfg);
	Gpio_Init(GpioPortA, GpioPin1, &stcGpioCfg);
	
    Gpio_ClrIO(GpioPortA, GpioPin0); 
	Gpio_ClrIO(GpioPortA, GpioPin1); 
}

/********************************************
在pulse 模式下,需要2路IO口输出5V脉冲
同时原PWM引脚也要输出低频脉冲
 *******************************************/
void Pulse_5V_12V_Output(void)
{
	if(PULSE_5V_ON_Flag)
	{
		PULSE_5V_ON_Flag = FALSE;
		Clr_IO_PWM;
		delay10us(1);		
		Set_IO_5VPulse;
		delay100us(1);
		Clr_IO_5VPulse;
		for (int i = 0; i < 7; i++)
		{
			delay100us(1);
		}
		Set_IO_LoadDischarge;
		delay100us(1);
		Clr_IO_LoadDischarge;		
	}
	if(PULSE_12V_ON_Flag)
	{
		PULSE_12V_ON_Flag = FALSE;
		Set_IO_PWM;
	}	
}

void Pulse_5V_Closed(void)
{
	Clr_IO_5VPulse;
	Clr_IO_LoadDischarge;
}


void Slide_resistor_detect(void)
{		
	static   e_res_pos  last_pos ;
    int sum = 0;	
	for(int i = 0; i < ADC_LOOP_NUM; i++)
	{
		sum += ADC.Restult5[i];
	}
	slide_res.Rvalue = sum/ADC_LOOP_NUM;
    if(slide_res.Rvalue >= SLIDE_RES_Rvalue_B)
    {
        slide_res.Pos = AB;  
    }
    if((slide_res.Rvalue >= SLIDE_RES_Rvalue_C)&&(slide_res.Rvalue < SLIDE_RES_Rvalue_B))
    {
        slide_res.Pos = BC;
    }
    if(slide_res.Rvalue <  SLIDE_RES_Rvalue_C)
    {
        slide_res.Pos = CD;  
    }
    if(slide_res.Pos != last_pos)
    {
         slide_res.pos_changed = TRUE;
    }
    last_pos = slide_res.Pos;
}


void Load_Current_detect(void)
{
	int adc_value = 0;	
	int sum = 0;
	for(int i = 0; i < ADC_LOOP_NUM; i++)
	{
		sum += ADC.Restult2[i];
	}
	adc_value = sum/ADC_LOOP_NUM;
	
	if( adc_value > 500) /*过流,总电流700mA左右*/
	{
		// PWM输出低电平.				
		
	}
	else  //过流恢复
	{
		
	
	}
}

/*******************************************************************************
**函数信息 ：void Update_BrakeGain_buffer()
**功能描述 ：过压或欠压保护
**输入参数 ：void
**输出参数 ：None
**备    注 ：		  
*******************************************************************************/
void Over_Voltage_detect(void)
{
	int adc_value = 0;	
  
	int sum = 0;
	for(int i = 0; i < ADC_LOOP_NUM; i++)
	{
		sum += ADC.Restult0[i];
	}
	adc_value = sum/ADC_LOOP_NUM;
	
	Pwr.voltage = 61*500*adc_value/4096;   /*51K(Up) + 10K(Down) 分压*/
    
    if(Pwr.voltage < 9000)
    {
    
    }
    else if(Pwr.voltage > 19000)
    {
    
        
    }	
}


/*********************************************************************
**函数信息 ：void App_PWM_out_init()
**功能描述 ：上电后确认pwm输出状态以及初始化
**输入参数 ：void
**输出参数 ：void
**备    注 ：
********************************************************************/
void App_Struct_data_init(void)
{
	delay1ms(100); /*等待ad转换完成*/
	
	Slide_resistor_detect();
		
	/*这里注意,Gain增益保存在Flash中,先读falsh,OK 赋值给全局变量;*/
	if( 0xff != Flash_ReadConfig())
	{
		gain.value = Flash_ReadConfig();
	}
	
	TxFrame_Gain.StdID = CAN_ID_GAIN;
	TxFrame_Gain.Data[0] = 0x00; // 滑阻
	TxFrame_Gain.Data[1] = 0x00;
	TxFrame_Gain.Data[2] = gain.value; 
	TxFrame_Gain.Data[3] = 0x00;	
	TxFrame_Gain.Data[4] = 0x00;	
	TxFrame_Gain.Data[5] = 0x00;
	TxFrame_Gain.Data[6] = 0x00;
	TxFrame_Gain.Data[7] = 0x00;	
	
	TxFrame_Keepalive.StdID = CAN_ID_KEEPALIVE;
	TxFrame_Keepalive.Data[0] = 0xC0; 
	TxFrame_Keepalive.Data[1] = 0x00; 
	TxFrame_Keepalive.Data[2] = 0xFF;	
	TxFrame_Keepalive.Data[3] = 0xFF;	
	TxFrame_Keepalive.Data[4] = 0xFF;	
	TxFrame_Keepalive.Data[5] = 0xFF;
	TxFrame_Keepalive.Data[6] = 0xFF;
	TxFrame_Keepalive.Data[7] = 0xFF;
	
}

/*更新数据*/
void update_CAN_Gain(uint8_t gain)
{      
    TxFrame_Gain.Data[2] = gain; 
     
     if(gain <= 2)
	 {	   
         if(slide_res.Pos == AB)
         {
             TxFrame_Gain.Data[0] = 0x6A;
             slide_res.Pos_BC_index = 0x0A;           
         }             
         if(slide_res.Pos == BC) /* 60 ~ 6A*/
         {
            slide_res.Pos_BC_index = 10*(slide_res.Rvalue - SLIDE_RES_Rvalue_C)/(SLIDE_RES_Rvalue_B - SLIDE_RES_Rvalue_C); 
            TxFrame_Gain.Data[0] = 0x60 + slide_res.Pos_BC_index;
         } 
         if(slide_res.Pos == CD)
         {
             // slow to zero :  0x60(xx times) --> 0x20(xx times) --> 0x00 (always)
              slide_res.Pos_BC_index = 0x00; 
         }  
	 }
	 else
	 {	  
         if(slide_res.Pos == AB)
         {
             TxFrame_Gain.Data[0] = 0xEA;
             slide_res.Pos_BC_index = 0x0A;
         }             
         if(slide_res.Pos == BC) /* 60 ~ 6A*/
         {
            slide_res.Pos_BC_index = 10*(slide_res.Rvalue - SLIDE_RES_Rvalue_C)/(SLIDE_RES_Rvalue_B - SLIDE_RES_Rvalue_C); 
            if(SlideRes_in_BC_Period()) 
            {
               TxFrame_Gain.Data[0] = 0xE0 + slide_res.Pos_BC_index;
            }
            else
            {
               TxFrame_Gain.Data[0] = 0x60 + slide_res.Pos_BC_index;
            }
         } 
         if(slide_res.Pos == CD)
         {
            // slow to zero :  0x60(1s) --> 0x20(3s) --> 0x00 (always)
             slide_res.Pos_BC_index = 0x00;           
         }   
	 }     
}



// 处理增益与pwm占空比
void App_key_process(void)
{
    static int cnt1 = 0;
    static int cnt2 = 0;
    if(Key_scan())
    {
        cnt1 = 0;
    }

    update_CAN_Gain(gain.value); 
     
    if(APP_CAN.CANSendFlag) /*100ms*/
	{
		APP_CAN.CANSendFlag = FALSE;
        if(slide_res.Pos == CD) 
        {
            if(gain.active_flg) /*按键事件驱动*/
            {    
                if(cnt1++ >= 10)  // 需要连续发送N次
                {
                    gain.active_flg = FALSE;	
                    TxFrame_Gain.Data[0] = 0x00;
                }
                else
                {
                    TxFrame_Gain.Data[0] |= 0x40;
                }    
            }
           if(slide_res.pos_changed) /*滑阻事件驱动*/
           {
              // slow to zero :  0x60(xx times) --> 0x20(xx times) --> 0x00 (always)  
               if(slide_res.pos_changed) 
               {               
                   cnt2++;
                   if(cnt2 <= 10)
                   {
                         TxFrame_Gain.Data[0] = 0x60;            
                   }            
                   if(cnt2 > 10 && cnt2 <= 40)
                   {
                         TxFrame_Gain.Data[0] = 0x20; 
                   }
                   if(cnt2 > 40)
                   {
                        TxFrame_Gain.Data[0] = 0x00;
                        cnt2 = 0;
                        slide_res.pos_changed =  FALSE;        
                   }
               }
           }     
        }
		CAN_send_Frame(&TxFrame_Gain, 8);         
	 }
}


void CAN_BUS_Process(void)
{ 
 
//	 if(APP_CAN.CAN_keepalive_SendFlag) /*心跳包数据,1s发送一次*/
//	 {
//		APP_CAN.CAN_keepalive_SendFlag = FALSE;	
//		CAN_send_Frame(&TxFrame_Keepalive, 8);
//	 }
		
	if(APP_CAN.BusErrorFlag)
	{
		APP_CAN.BusErrorFlag = FALSE;
		M0P_CAN->CFG_STAT = 0x00;
	}
}

/*
pwm 和脉冲模式切换,testOK
*/
void PWM_mod_change(e_pwm_mod mdoe)
{	
    if(mdoe == PULSE)
    {
        if(PWM_Mode == PULSE)
        {
            return;
        } 
        PWMPin_reinit_NormalPin();/* 防止切换瞬间有较长的高电平*/
        BSP_Timer1_init(1500);
        PWM_Mode = PULSE;  
    }
    
    if(mdoe == PWM)
    {
        if(PWM_Mode == PWM)
        {
            return;
        } 
        Reset_RstPeripheral0(ResetMskBaseTim); /* 防止切换瞬间有较长的高电平*/       
		BSP_PWM_Config();// 切换到PWM模式
        PWM_Mode = PWM;  
    }
}



void PWM_Output1(void)
{   
    uint8_t g_duty = 0;
    uint8_t ratio = slide_res.Pos_BC_index;  /*[0 ~ A]*/
    uint8_t lowest_duty = 7; /*最小占空比 7% */
	if(gain.value <= 2)
	{
		 PWM_mod_change(PULSE);	 
         Pulse_5V_12V_Output();   
	}
	else  // 再根据滑阻进一步细分pwm和pulse模式
	{	     
       if(slide_res.Pos == BC) 
       {
           if(SlideRes_in_BC_Period())//PWM-PULSE 切换的临界点会随着增益的变化而变化 
           {
                PWM_mod_change(PWM);  
                ratio = ratio-Gain_Res_Margin[gain.value/2][1]&0x0f;
                g_duty = (Gain_tab[gain.value/2][1] - lowest_duty)*ratio/10 + lowest_duty;            
                BSP_PWM_SetDuty(g_duty);  
           }
           else
           {
                Pulse_5V_12V_Output(); 
           
           }
       }
       if( slide_res.Pos == AB ) /* Max PWM @ some gain*/
       {
            PWM_mod_change(PWM); 
            BSP_PWM_SetDuty(Gain_tab[gain.value/2][1]);
       }
       if(slide_res.Pos == CD)
       {
            PWM_mod_change(PULSE);	 
            Pulse_5V_12V_Output();     
       }
	} 
}


// 根据增益判断临界点
static bool SlideRes_in_BC_Period(void)
{
    if(slide_res.Pos == BC)
    {
        if( (0xE0 + slide_res.Pos_BC_index) >= Gain_Res_Margin[gain.value/2][1])
        {
              return true; 
        }
    }
    return false;
}
